using System;
using System.IO;
using System.Collections.Generic;
using Subsync.Core.Subversion;
using Subsync.Core.Sync;
using System.Diagnostics;

namespace Subsync.Core.Excludes
{
	/// <summary>
	/// Author: Hoang Duc
	/// </summary>
    public class Exclude
    {        
        private string file_path;

        public Exclude()
        {
        }

        public Exclude(string filePath)
        {
            this.file_path = filePath;
        }

        public bool IsIgnored()
        {
            try
            {
                SVNStatus fileStatus = new SVNStatus(this.file_path);
                fileStatus.Execute();
                if (fileStatus.statusInfo.pathChangeType == "I")
                    return true;
                else
                    return false;
            }
            catch (Exception)
            {
                Exclude parent = new Exclude(Path.GetDirectoryName(this.file_path));
                return parent.IsIgnored();
            }
        }

        public static List<string> GetIgnoredPaths(Sync.Sync s)
        {
            List<string> ignoredPaths = new List<string>();

            string[] files = Directory.GetFiles(s.working_copy_path,"*",SearchOption.AllDirectories);
            string[] dirs = Directory.GetDirectories(s.working_copy_path, "*", SearchOption.AllDirectories);

            Exclude checker;

            foreach (string f in files)
            {
                checker = new Exclude(f);
                f.Replace(Path.DirectorySeparatorChar, '/');
                if (checker.IsIgnored())
                    ignoredPaths.Add(f);
            }

            foreach (string d in dirs)
            {
                checker = new Exclude(d);
                d.Replace(Path.DirectorySeparatorChar, '/');
                if (checker.IsIgnored())
                    ignoredPaths.Add(d);
            }
            return ignoredPaths;
        }

        public bool Execute()
        {
            if (!File.Exists(this.file_path) && !Directory.Exists(file_path))
                throw new FolderDoesNotExist("The file / folder provided does not exist.");

            if (!File.Exists(file_path) && !Directory.Exists(file_path))
                throw new FolderDoesNotExist("The working copy item provided does not exist.");

            string dir = new java.io.File(file_path).getParent();
            string file = new java.io.File(file_path).getName();

            if (!IsIgnored())
            {
                Subsync.Core.Sync.Sync s = GetSync(file_path);
                s.Execute();
                SVNPropGet propGetter = new SVNPropGet(dir, "svn:ignore", "undefined", "working");
                propGetter.Execute();
                file = propGetter.value + file;
                new SVNPropSet(dir, "svn:ignore", file.Trim()).Execute();
                try
                {
                    new SVNRemove(file_path, false, false).Execute();
                    string parent = Path.GetDirectoryName(file_path);
                    new SVNCommit(parent).Execute();
					
                }
                catch (Exception)
                {
                    Debug.WriteLine("File path not versioned.");
                }
            }
            else
            {
                try
                {
                    SVNPropGet propGetter = new SVNPropGet(dir, "svn:ignore", "undefined", "working");
                    propGetter.Execute();
                    file = propGetter.value.Replace(file + System.Environment.NewLine, "");
                    new SVNPropSet(dir, "svn:ignore", file.Trim()).Execute();
                }
                catch (Exception)
                {
                    Debug.WriteLine("File is already inside an ignored folder");
                }
            }
            return IsIgnored();
        }

		Subsync.Core.Sync.Sync GetSync (string filepath)
		{
			List<Subsync.Core.Sync.Sync> all_syncs = new Config ().GetAllSyncs ();
			foreach (Subsync.Core.Sync.Sync s in all_syncs) {
				if (filepath.StartsWith (s.working_copy_path))
					return s;
			}
			return null;
		}
    }
}

